package vip.xiaonuo.vehicle.vehicleTraffic.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import lombok.SneakyThrows;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.Reactor;
import reactor.event.Event;
import vip.xiaonuo.facedoor.modular.devicebase.entity.DeviceBase;
import vip.xiaonuo.facedoor.modular.devicebase.service.DeviceBaseService;
import vip.xiaonuo.facedoor.modular.visitor.entity.Visitor;
import vip.xiaonuo.facedoor.modular.visitor.service.VisitorService;
import vip.xiaonuo.sys.modular.file.enums.FileTypeEnum;
import vip.xiaonuo.sys.modular.file.service.SysFileInfoService;
import vip.xiaonuo.vehicle.common.constant.Constants;
import vip.xiaonuo.vehicle.common.enums.PersonnelTypeEnum;
import vip.xiaonuo.vehicle.common.reactor.dto.RecorderDto;
import vip.xiaonuo.vehicle.modular.vehicleblacklist.entity.VehicleBlacklist;
import vip.xiaonuo.vehicle.modular.vehicleblacklist.service.VehicleBlacklistService;
import vip.xiaonuo.vehicle.modular.vehicleinfo.entity.VehicleInfo;
import vip.xiaonuo.vehicle.modular.vehicleinfo.service.VehicleInfoService;
import vip.xiaonuo.vehicle.vehicleTraffic.dto.HeartBeatDTO;
import vip.xiaonuo.vehicle.vehicleTraffic.dto.PlateResult;
import vip.xiaonuo.vehicle.vehicleTraffic.service.VehicleTrafficService;
import vip.xiaonuo.vehicle.common.util.Base64ToImg;

import javax.annotation.Resource;
import java.util.Calendar;
import java.util.Date;
import java.util.List;


/**
 * 车辆通行服务实现
 *
 * @author cad
 * @date 2023/03/22
 */
@Service
public class VehicleTrafficServiceImpl implements VehicleTrafficService {
    @Resource
    private DeviceBaseService deviceBaseService;
    @Resource
    private VehicleInfoService vehicleInfoService;
    @Resource
    private SysFileInfoService sysFileInfoService;
    @Resource
    private VisitorService visitorService;
    @Resource
    private VehicleBlacklistService vehicleBlacklistService;
    @Resource
    private Reactor reactor;

    @Override
    public void registerAndHeartBeat(HeartBeatDTO heartBeatDTO) {
        DeviceBase one = deviceBaseService.getOne(new LambdaQueryWrapper<DeviceBase>().eq(DeviceBase::getRegistrationCode, heartBeatDTO.getSerialno()));
        if (one == null) {
            DeviceBase deviceBase = new DeviceBase().setCabinetIp(heartBeatDTO.getIpaddr()).setCabinetPort(heartBeatDTO.getPort()).setRegistrationCode(heartBeatDTO.getSerialno()).setName(heartBeatDTO.getDevice_name()).setDevicePassword(heartBeatDTO.getPass_wd()).setDeviceType("8").setDeviceState("1").setLastOnlineTime(new Date());
            deviceBaseService.save(deviceBase);
        } else {
            one.setDevicePassword(heartBeatDTO.getPass_wd()).setCabinetIp(heartBeatDTO.getIpaddr()).setCabinetPort(heartBeatDTO.getPort()).setName(heartBeatDTO.getDevice_name()).setDeviceState("1").setLastOnlineTime(new Date());
            deviceBaseService.updateById(one);
        }
    }

    /**
     * 车闸通行请求
     *
     * @return {@link Boolean}
     */
    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    @Override
    public Boolean checkVehicleTraffic(PlateResult plateRuselt) {
        MultipartFile file = null;
        if (StringUtils.isNotBlank(plateRuselt.getAlarmInfoPlate().getResult().getPlateResult().getImageFragmentFile())) {
            // 临时文件，保存之后还会再删除
            file = Base64ToImg.getMultipartFile(plateRuselt.getAlarmInfoPlate().getResult().getPlateResult().getImageFragmentFile(), "temp");
        }
        final String imagePath = file == null ? null : sysFileInfoService.uploadFileAndReturnUrl(file, FileTypeEnum.RECORD);
        //车牌号
        String license = plateRuselt.getAlarmInfoPlate().getResult().getPlateResult().getLicense();
        List<VehicleBlacklist> list = vehicleBlacklistService.list(new LambdaQueryWrapper<VehicleBlacklist>().eq(VehicleBlacklist::getLicensePlateNumber, license));
        if (!CollectionUtils.isEmpty(list)) {
            return false;
        }
        //设备序列号
        String serialNumber = plateRuselt.getAlarmInfoPlate().getSerialno();
        //通行设备
        DeviceBase vehicleDevice = deviceBaseService.getOne(new LambdaQueryWrapper<DeviceBase>().eq(DeviceBase::getRegistrationCode, serialNumber));
        //根据车牌查询车辆信息(如果存在，说明是内部人员车辆)
        VehicleInfo vehicleInfo = vehicleInfoService.getOne(new LambdaQueryWrapper<VehicleInfo>().eq(VehicleInfo::getLicensePlateNumber, license));
        if (ObjectUtils.isNotEmpty(vehicleInfo)) {
            getTrafficRecorder(imagePath, vehicleDevice, vehicleInfo, PersonnelTypeEnum.MEMBER_USER.getFlag());
            return true;
        }
        Visitor visitor = visitorService.getOne(new LambdaQueryWrapper<Visitor>().eq(Visitor::getCarNum, license).eq(Visitor::getStatus, 1));
        if (ObjectUtils.isNotEmpty(visitor)) {
            Calendar calendar = Calendar.getInstance();
            Date time = calendar.getTime();
            if (time.after(visitor.getVisitStartDate()) && time.before(visitor.getVisitEndDate())) {
                VehicleInfo vehicleInfo1 = new VehicleInfo();
                vehicleInfo1.setLicensePlateNumber(license);
                getTrafficRecorder(imagePath, vehicleDevice, vehicleInfo1, PersonnelTypeEnum.VISITOR.getFlag());
                return true;
            }
        }

        VehicleInfo vehicleInfo1 = new VehicleInfo();
        vehicleInfo1.setLicensePlateNumber(license);
        getTrafficRecorder(imagePath, vehicleDevice, vehicleInfo1, PersonnelTypeEnum.STRANGER.getFlag());
        return false;
    }

    private void getTrafficRecorder(String imagePath, DeviceBase vehicleDevice, VehicleInfo vehicleInfo, Integer personType) {
        reactor.notify(Constants.RECORDER_TOPIC, Event.wrap(new RecorderDto().setDeviceBase(vehicleDevice).setVehicleInfo(vehicleInfo).setImg(imagePath).setPersonType(personType)));
    }
}
